package com.wq.httpclientcore.common;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wq.httpclientcore.entities.po.ApiConfig;
import com.wq.httpclientcore.entities.po.AuthConfig;
import com.wq.httpclientcore.model.HttpResponseWrapper;
import com.wq.httpclientcore.service.ApiConfigService;
import com.wq.httpclientcore.service.AuthConfigService;
import com.wq.httpclientcore.utils.CommonUtils;
import com.wq.httpclientcore.utils.PlaceholderResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class CommonClient implements ICommonClient {

    private static final Logger logger = LoggerFactory.getLogger(CommonClient.class);

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private ApiConfigService apiConfigService;

    @Autowired
    private AuthConfigService authConfigService;


    private final ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Override
    public HttpResponseWrapper<Object> callApi(Long apiId, Map<String, Object> dynamicParams, Map<String, String> dynamicHeaders, Map<String,Object> dynamicBody, Integer pageSize, Integer pageNo) {
        long startTime = System.currentTimeMillis(); // 记录方法开始时间
        try {
            // 检查 apiId 是否为空
            if (apiId == null) {
                return new HttpResponseWrapper<>(null, 400, "API id不能为 null 或为空",null);
            }
            // 从 Redis 获取 ApiConfig
            String key = "apiConfig:" + apiId;
            ApiConfig apiConfig = (ApiConfig) redisTemplate.opsForValue().get(key);
            if (apiConfig == null) {
                // 从数据库加载 API 配置
                apiConfig = apiConfigService.lambdaQuery().eq(ApiConfig::getId, apiId).one();
                if (apiConfig != null) {
                    // 将数据存入 Redis
                    redisTemplate.opsForValue().set(key, apiConfig, 60, TimeUnit.MINUTES);
                }
            }

            // 加载鉴权配置
            if (apiConfig.getAuthConfigId() != null) {
                AuthConfig authConfig = authConfigService.getById(apiConfig.getAuthConfigId());
                if (authConfig != null) {
                    apiConfig.setAuthConfig(authConfig);
                }
            }

            return sendRequest(apiConfig, dynamicParams, dynamicHeaders, dynamicBody, pageSize, pageNo);
        } finally {
            long endTime = System.currentTimeMillis(); // 记录方法结束时间
            long elapsedTime = endTime - startTime; // 计算方法运行时间
            logger.info("callApi 方法运行时间: {} 毫秒", elapsedTime);
        }
    }

    /**
     * 发送 HTTP 请求的通用方法
     *
     * @param apiConfig      API 配置信息
     * @param dynamicParams  动态请求参数
     * @param dynamicHeaders 动态请求头
     * @param dynamicBody    动态请求体
     * @param pageSize
     * @param pageNo
     * @return 响应包装对象
     */
    private HttpResponseWrapper<Object> sendRequest(ApiConfig apiConfig, Map<String, Object> dynamicParams, Map<String, String> dynamicHeaders, Map<String, Object> dynamicBody, Integer pageSize, Integer pageNo) {
        // 检查基础 URL 和路径
        String baseUrl = apiConfig.getBaseUrl();
        String path = apiConfig.getPath();
        if (baseUrl == null || baseUrl.trim().isEmpty() || path == null || path.trim().isEmpty()) {
            return new HttpResponseWrapper<>(null, 400, "URL 或路径不能为 null 或为空",null);
        }

        // 检查 HTTP 方法
        String method = apiConfig.getMethod();
        if (method == null || method.trim().isEmpty()) {
            return new HttpResponseWrapper<>(null, 400, "HTTP 方法不能为 null 或为空",null);
        }

        // 处理鉴权
        AuthConfig authConfig = apiConfig.getAuthConfig();
        if (ObjectUtils.isNotEmpty(authConfig)) {
            try {
                // 调用鉴权接口获取 token
                Map<String, Object> authResponse = callAuthApi(authConfig);
                if (authResponse != null) {
                    // 解析鉴权结果集
                    Map<String, Object> authData = (Map<String, Object>) authResponse.get("data");
                    logger.info("鉴权结果集: {}", authResponse);
                    if (authData != null) {
                        String accessToken = (String) authData.get("access_token");
                        String tokenType = (String) authData.get("token_type");

                        // 构建请求头映射
                        String authHeaderMapping = authConfig.getAuthHeaderMapping();
                        if (authHeaderMapping != null && !authHeaderMapping.isEmpty()) {
                            Map<String, Object> tokenValues = new HashMap<>();
                            tokenValues.put("access_token", accessToken);
                            tokenValues.put("token_type", tokenType);

                            // 解析请求头映射
                            String resolvedHeader = PlaceholderResolver.resolve(authHeaderMapping, tokenValues);
                            if (dynamicHeaders == null) {
                                dynamicHeaders = new HashMap<>();
                            }
                            Map<String, Object> resolvedHeaderMap = objectMapper.readValue(resolvedHeader, Map.class);
                            for (Map.Entry<String, Object> entity : resolvedHeaderMap.entrySet()) {
                                dynamicHeaders.put(entity.getKey(), entity.getValue().toString());
                            }
                        }
                    }
                }
            } catch (Exception e) {
                logger.error("鉴权失败: {}", e.getMessage());
                return new HttpResponseWrapper<>(null, 500, "鉴权失败: " + e.getMessage(),null);
            }
        }

        // 构建完整的 URL
        String url = baseUrl + path;

        // 构建请求头
        HttpHeaders headers = buildHeaders(apiConfig.getRequestHeaders(), dynamicHeaders);
        logger.info("请求头: {}", headers);
        // 构建请求参数
        Map<String, Object> requestParams = buildParams(apiConfig.getRequestParams(), dynamicParams);
        url = buildUrlWithParams(url, requestParams);

        logger.info("最终生成的 URL: {}", url);

        // 构建请求体
        Object requestBody = buildRequestBody(apiConfig.getRequestBody(), dynamicBody);

        // 发送 HTTP 请求
        try {
            HttpEntity<Object> httpEntity = new HttpEntity<>(requestBody, headers);
            ParameterizedTypeReference<Object> typeReference = new ParameterizedTypeReference<>() {};
            ResponseEntity<Object> responseEntity = restTemplate.exchange(
                    url,
                    HttpMethod.valueOf(method),
                    httpEntity,
                    typeReference,
                    requestParams
            );
            Object body = responseEntity.getBody();
            logger.info("响应体: {}", body);
            List<Object> dataList = new ArrayList<>();

            if (body instanceof Map) {
                Map<String, Object> responseMap = (Map<String, Object>) body;
                //这个不确定是否是data todo
                Object dataObj = responseMap.get("data");
                if (dataObj instanceof List) {
                    dataList = (List<Object>) dataObj;
                }else{
                    return new HttpResponseWrapper<>(body, responseEntity.getStatusCode().value(), null,1);
                }
            } else if (body instanceof List) {
                dataList = (List<Object>) body;
            }
            if (pageSize == null || pageNo == null) {
                return new HttpResponseWrapper<>(dataList, responseEntity.getStatusCode().value(), null,dataList.size());
            } else {
                List<Object> result = CommonUtils.pageList(dataList, pageNo, pageSize);
                return new HttpResponseWrapper<>(result, responseEntity.getStatusCode().value(), null,result.size());
            }
        } catch (Exception e) {
            logger.error("请求失败: {}", e.getMessage());
            return new HttpResponseWrapper<>(null, 500, e.getMessage(),null);
        }
    }

    /**
     * 调用鉴权接口
     * @param authConfig 鉴权配置
     * @return 鉴权接口的响应结果
     */
    private Map<String, Object> callAuthApi(AuthConfig authConfig) {
        String authMethod = authConfig.getAuthMethod();
        String authUrl = authConfig.getAuthUrl();
        Map<String, Object> authRequestParams = authConfig.getAuthRequestParams();
        Map<String, Object> authRequestHeaders = authConfig.getAuthRequestHeaders();
        Map<String, Object> authRequestBody = authConfig.getAuthRequestBody();

        // 构建鉴权请求头
        HttpHeaders authHeaders = buildHeaders(authRequestHeaders, null);

        // 构建鉴权请求参数
        Map<String, Object> authParams = buildParams(authRequestParams, null);

        // 构建鉴权请求体
        Object authBody = buildRequestBody(authRequestBody, null);

        // 构建带参数的 URL
        String authFullUrl = buildUrlWithParams(authUrl, authParams);

        // 发送鉴权请求
        HttpEntity<Object> httpEntity = new HttpEntity<>(authBody, authHeaders);
        ParameterizedTypeReference<Map<String, Object>> typeReference = new ParameterizedTypeReference<>() {};
        ResponseEntity<Map<String, Object>> responseEntity = restTemplate.exchange(
                authFullUrl,
                HttpMethod.valueOf(authMethod),
                httpEntity,
                typeReference,
                authParams
        );

        if (responseEntity.getStatusCode() == HttpStatus.OK && responseEntity.getBody() != null) {
            return responseEntity.getBody();
        }
        throw new RuntimeException("鉴权接口调用失败");
    }

    /**
     * 构建请求头
     * @param configHeaders 配置中的请求头
     * @param dynamicHeaders 动态请求头
     * @return 合并后的请求头
     */
    private HttpHeaders buildHeaders(Map<String, Object> configHeaders, Map<String, String> dynamicHeaders) {
        HttpHeaders headers = new HttpHeaders();
        if (configHeaders != null) {
            configHeaders.forEach((key, value) -> {
                if (key != null && value != null) {
                    headers.add(key, value.toString());
                }
            });
        }
        if (dynamicHeaders != null) {
            dynamicHeaders.forEach((key, value) -> {
                if (key != null && value != null) {
                    headers.set(key, value); // 动态请求头优先级高于配置中的请求头
                }
            });
        }
        headers.setContentType(MediaType.APPLICATION_JSON);
        return headers;
    }

    /**
     * 构建请求参数
     * @param configParams 配置中的请求参数
     * @param dynamicParams 动态请求参数
     * @return 合并后的请求参数
     */
    private Map<String, Object> buildParams(Map<String, Object> configParams, Map<String, Object> dynamicParams) {
        Map<String, Object> requestParams = new HashMap<>();
        if (configParams != null) {
            requestParams.putAll(configParams);
        }
        if (dynamicParams != null) {
            requestParams.putAll(dynamicParams); // 动态参数优先级高于配置中的参数
        }
        return requestParams;
    }

    /**
     * 构建带参数的 URL
     * @param url 基础 URL
     * @param requestParams 请求参数
     * @return 带参数的 URL
     */
    private String buildUrlWithParams(String url, Map<String, Object> requestParams) {
        if (requestParams != null && !requestParams.isEmpty()) {
            StringBuilder queryString = new StringBuilder();
            for (Map.Entry<String, Object> entry : requestParams.entrySet()) {
                if (queryString.length() > 0) {
                    queryString.append("&");
                }
                queryString.append(entry.getKey()).append("={").append(entry.getKey()).append("}");
            }
            if (queryString.length() > 0) {
                url += "?" + queryString.toString();
            }
        }
        return url;
    }

    /**
     * 构建请求体
     * @param configBody 配置中的请求体
     * @param dynamicBody 动态请求体
     * @return 最终的请求体
     */
    private Object buildRequestBody(Map<String, Object> configBody, Map<String, Object> dynamicBody) {
        if (dynamicBody != null && !dynamicBody.isEmpty()) {
            return dynamicBody;
        }else if (configBody != null && !configBody.isEmpty()) {
            return configBody;
        }else{
            return null;
        }

    }
}